/*
 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
 */

#ifndef __LSTREAM_H__
#define __LSTREAM_H__

#include <stdint.h>
#include <stddef.h>
#include <aos/kernel.h>


#define STREAM_OPS_MAX          (16)
#define STREAM_PROTOCOLS_MAX     (5)

typedef struct lstream_cls lstream_cls_t;

struct lstream_ops {
    const char                *name;
    uint8_t                   type;
    const char*               protocols[STREAM_PROTOCOLS_MAX];

    int      (*open)          (lstream_cls_t *o);
    int      (*read)          (lstream_cls_t *o, uint8_t *buf, size_t count);
    int      (*write)         (lstream_cls_t *o, const uint8_t *buf, size_t count);
    int      (*seek)          (lstream_cls_t *o, int32_t pos);
    int      (*control)       (lstream_cls_t *o, int cmd, void *arg, size_t *arg_size);
    int      (*close)         (lstream_cls_t *o);
};

struct lstream_cls {
    // int32_t                   buf_pos;
    // int32_t                   buf_len;

    int64_t                   pos;
    int64_t                   size;                    ///< length of the stream

    char                      *url;
    uint8_t                   eof;

    void                      *priv;
    const struct lstream_ops   *ops;
    aos_mutex_t               lock;
} ;

typedef enum lstream_type {
    LSTREAM_TYPE_UNKNOWN,
    LSTREAM_TYPE_FILE,
    LSTREAM_TYPE_MEM,
} lstream_type_t;

/**
 * @brief  regist stream ops
 * @param  [in] ops
 * @return 0/-1
 */
int lstream_ops_register(const struct lstream_ops *ops);

/**
 * @brief  regist stream ops
 * @param  [in] ops
 */
void lstream_ops_register_all(void);

/**
* @brief  open a stream
* @param  [in] url
* @param  [in] stm_cnf
* @return NULL on error
*/
lstream_cls_t* lstream_open(const char *url);

/**
 * @brief  read from a stream
 * @param  [in] o
 * @param  [in] buf
 * @param  [in] count
 * @return -1 when err happens
 */
int lstream_read(lstream_cls_t *o, uint8_t *buf, size_t count);

/**
 * @brief  write data to a stream
 * @param  [in] o
 * @param  [in] buf
 * @param  [in] count
 * @return -1 when err happens
 */
int lstream_write(lstream_cls_t *o, const uint8_t *buf, size_t count);

/**
 * @brief  close a stream
 * @param  [in] o
 * @return 0/-1
 */
int lstream_close(lstream_cls_t *o);

/**
 * @brief  stream is eof whether
 * @param  [in] o
 * @return 0/1
 */
int lstream_is_eof(lstream_cls_t *o);

/**
 * @brief  get the stream size
 * @param  [in] o
 * @return -1 on err
 */
int64_t lstream_get_size(lstream_cls_t *o);

/**
 * @brief  get the url
 * @param  [in] o
 * @return
 */
const char* lstream_get_url(lstream_cls_t *o);

#endif /* __LSTREAM_H__ */

